From 907d3e969c58187cfdfa7f28b8b65c147077e96b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 10 Jul 2007 23:37:42 +0100 Subject: [PATCH] vmx: Never use physical addresses above 4GB for VMCS state on i386. Thsi requires special allocation of the vlapic regs page, but does let us get rid of some top-half writes to a few VMCS fields. Assert a few more facts about the VMX_BASIC_MSR. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vlapic.c | 9 ++++++++- xen/arch/x86/hvm/vmx/vmcs.c | 15 ++++++++++----- xen/arch/x86/hvm/vmx/vmx.c | 6 +----- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 3075ee58a6..712c7c7523 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -915,10 +915,17 @@ HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs, int vlapic_init(struct vcpu *v) { struct vlapic *vlapic = vcpu_vlapic(v); + unsigned int memflags = 0; HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "%d", v->vcpu_id); - vlapic->regs_page = alloc_domheap_page(NULL); +#ifdef __i386__ + /* 32-bit VMX may be limited to 32-bit physical addresses. */ + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + memflags = MEMF_bits(32); +#endif + + vlapic->regs_page = alloc_domheap_pages(NULL, 0, memflags); if ( vlapic->regs_page == NULL ) { dprintk(XENLOG_ERR, "alloc vlapic regs error: %d/%d\n", diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 0636502185..aee5b0e517 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -151,6 +151,14 @@ void vmx_init_vmcs_config(void) /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ BUG_ON((vmx_msr_high & 0x1fff) > PAGE_SIZE); + +#ifdef __x86_64__ + /* IA-32 SDM Vol 3B: 64-bit CPUs always have VMX_BASIC_MSR[48]==0. */ + BUG_ON(vmx_msr_high & (1u<<16)); +#endif + + /* Require Write-Back (WB) memory type for VMCS accesses. */ + BUG_ON(((vmx_msr_high >> 18) & 15) == 6); } static struct vmcs_struct *vmx_alloc_vmcs(void) @@ -422,11 +430,8 @@ static void construct_vmcs(struct vcpu *v) if ( cpu_has_vmx_tpr_shadow ) { - paddr_t virt_page_ma = page_to_maddr(vcpu_vlapic(v)->regs_page); - __vmwrite(VIRTUAL_APIC_PAGE_ADDR, virt_page_ma); -#if defined (CONFIG_X86_PAE) - __vmwrite(VIRTUAL_APIC_PAGE_ADDR_HIGH, virt_page_ma >> 32); -#endif + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, + page_to_maddr(vcpu_vlapic(v)->regs_page)); __vmwrite(TPR_THRESHOLD, 0); } diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index b9e3825377..dbe9577103 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -2718,7 +2718,7 @@ static void vmx_free_vlapic_mapping(struct domain *d) static void vmx_install_vlapic_mapping(struct vcpu *v) { - paddr_t virt_page_ma, apic_page_ma; + unsigned long virt_page_ma, apic_page_ma; if ( !cpu_has_vmx_virtualize_apic_accesses ) return; @@ -2730,10 +2730,6 @@ static void vmx_install_vlapic_mapping(struct vcpu *v) vmx_vmcs_enter(v); __vmwrite(VIRTUAL_APIC_PAGE_ADDR, virt_page_ma); __vmwrite(APIC_ACCESS_ADDR, apic_page_ma); -#if defined (CONFIG_X86_PAE) - __vmwrite(VIRTUAL_APIC_PAGE_ADDR_HIGH, virt_page_ma >> 32); - __vmwrite(APIC_ACCESS_ADDR_HIGH, apic_page_ma >> 32); -#endif vmx_vmcs_exit(v); } -- 2.30.2